//package com.baizw.cultivation.common.authenticate.intercept;
//
//import cn.hutool.core.map.MapUtil;
//import cn.hutool.core.util.ArrayUtil;
//import cn.hutool.core.util.StrUtil;
//import com.baizw.cultivation.common.authenticate.annotation.DataAuth;
//import com.baizw.cultivation.common.authenticate.annotation.EnableDataAuth;
//import lombok.AllArgsConstructor;
//import lombok.extern.slf4j.Slf4j;
//import org.apache.ibatis.executor.Executor;
//import org.apache.ibatis.mapping.BoundSql;
//import org.apache.ibatis.mapping.MappedStatement;
//import org.apache.ibatis.mapping.SqlCommandType;
//import org.apache.ibatis.mapping.SqlSource;
//import org.apache.ibatis.plugin.*;
//import org.apache.ibatis.session.ResultHandler;
//import org.apache.ibatis.session.RowBounds;
//import org.springframework.beans.BeansException;
//import org.springframework.boot.context.event.ApplicationStartedEvent;
//import org.springframework.context.ApplicationContext;
//import org.springframework.context.ApplicationContextAware;
//import org.springframework.context.ApplicationListener;
//
//import java.lang.reflect.Method;
//import java.util.HashMap;
//import java.util.Map;
//import java.util.Properties;
//
///**
// * 数据权限过滤拦截器
// *
// * @author 剧终1204
// * @version V1.0
// * @date 2020年05月22日 10:19:39
// */
//@Slf4j
////@Component
//@Intercepts({@Signature(type = Executor.class, method = "query", args = {MappedStatement.class, Object.class, RowBounds.class, ResultHandler.class})})
//public class PermissionHelper implements Interceptor, ApplicationContextAware, ApplicationListener<ApplicationStartedEvent> {
//
//    private static ApplicationContext context;
//    private Map<String, DataAuth> DATA_AUTH_MAP = new HashMap<>(16);
//
//    /**
//     * 初始化获取Spring上下文对象
//     *
//     * @param applicationContext 上下文对象
//     * @throws BeansException Bean异常
//     */
//    @Override
//    public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
//        context = applicationContext;
//    }
//
//    /**
//     * 初始化被注解数据权限注解标注的Bean
//     * 将其相关信息放入 DATA_AUTH_MAP
//     *
//     * @param event Spring ApplicationStartEvent
//     */
//    @Override
//    public void onApplicationEvent(ApplicationStartedEvent event) {
//        Map<String, Object> beansWithAnnotation = event.getApplicationContext().getBeansWithAnnotation(EnableDataAuth.class);
//        if (MapUtil.isNotEmpty(beansWithAnnotation)) {
//            beansWithAnnotation.values().forEach(x -> {
//                Class<?> clazz = x.getClass().getInterfaces()[0];
//                EnableDataAuth enableDataAuth = clazz.getAnnotation(EnableDataAuth.class);
//                if (ArrayUtil.isNotEmpty(enableDataAuth.value())) {
//                    DataAuth[] dataAuthArray = enableDataAuth.value();
//                    for (DataAuth dataAuth : dataAuthArray) {
//                        putAnnotationPresent(clazz.getName(), dataAuth.methodName(), dataAuth);
//                    }
//                }
//                Method[] declaredMethods = clazz.getDeclaredMethods();
//                if (ArrayUtil.isNotEmpty(declaredMethods)) {
//                    for (Method declaredMethod : declaredMethods) {
//                        if (declaredMethod.isAnnotationPresent(DataAuth.class)) {
//                            DataAuth dataAuth = declaredMethod.getAnnotation(DataAuth.class);
//                            putAnnotationPresent(clazz.getName(), dataAuth.methodName(), dataAuth);
//                        }
//                    }
//                }
//            });
//        }
//    }
//
//    @Override
//    public Object intercept(Invocation invocation) throws Throwable {
//        MappedStatement mappedStatement = (MappedStatement) invocation.getArgs()[0];
//
//        // 只对查询sql拦截
//        if (!SqlCommandType.SELECT.equals(mappedStatement.getSqlCommandType())) {
//            return invocation.proceed();
//        }
//
//        // String mSql = sql;
//        // 注解逻辑判断 添加注解了才拦截追加
//        String statementId = mappedStatement.getId();
////        if (DATA_AUTH_MAP.containsKey(statementId)) {
////            Class<?> clazz = ClassUtil.loadClass(StrUtil.subBefore(statementId, StrUtil.DOT, true));
////            DataAuth action = DATA_AUTH_MAP.get(statementId);
////            if (StrUtil.isNotBlank(action.authSQL())) {
////                // 获取拦截SQL
////                String authSQL = action.authSQL();
////                try {
////                    // 分离原始SQL
////                    Object parameter = null;
////                    if (ArrayUtil.isNotEmpty(invocation.getArgs())) {
////                        parameter = invocation.getArgs()[1];
////                    }
////
////                    BoundSql boundSql = mappedStatement.getBoundSql(parameter);
////                    MappedStatement newStatement = newMappedStatement(mappedStatement, new BoundSqlSqlSource(boundSql));
////                    MetaObject msObject = MetaObject.forObject(newStatement, new DefaultObjectFactory(), new DefaultObjectWrapperFactory(), new DefaultReflectorFactory());
////
////                    // 通过JSqlParser解析 原有sql,追加sql条件
////                    CCJSqlParserManager parserManager = new CCJSqlParserManager();
////
////                    Select select = (Select) parserManager.parse(new StringReader(boundSql.getSql()));
////                    PlainSelect selectBody = (PlainSelect) select.getSelectBody();
////                    Expression whereExpression = CCJSqlParserUtil.parseCondExpression(authSQL);
////                    selectBody.setWhere(new AndExpression(selectBody.getWhere(), new Parenthesis(whereExpression)));
////
////                    // 修改sql
////                    msObject.setValue("sqlSource.boundSql.sql", selectBody.toString());
////                    invocation.getArgs()[0] = newStatement;
////                } catch (Exception e) {
////                    log.error("SQL重新织入异常", e);
////                }
////            }
////        }
//        return invocation.proceed();
//    }
//
//
//    /**
//     * 当目标类是Executor类型时，才包装目标类，否者直接返回目标本身,减少目标被代理的次数
//     *
//     * @param target
//     * @return
//     */
//    @Override
//    public Object plugin(Object target) {
//        if (target instanceof Executor) {
//            return Plugin.wrap(target, this);
//        }
//        return target;
//    }
//
//    @Override
//    public void setProperties(Properties arg0) {
//        // TODO Auto-generated method stub
//    }
//
//    /**
//     * 存储被 {@DataAuth} 标记的方法
//     *
//     * @param className  类名称
//     * @param methodName 方法名称
//     * @param dataAuth   注解内容
//     * @see DataAuth
//     */
//    private void putAnnotationPresent(String className, String methodName, DataAuth dataAuth) {
//        DATA_AUTH_MAP.put(StrUtil.format("{}.{}", className, methodName), dataAuth);
//    }
//
//    /**
//     * 重新构建 MappedStatement
//     *
//     * @param mappedStatement
//     * @param newSqlSource
//     * @return
//     */
//    private MappedStatement newMappedStatement(MappedStatement mappedStatement, SqlSource newSqlSource) {
//        MappedStatement.Builder builder = new MappedStatement.Builder(mappedStatement.getConfiguration(), mappedStatement.getId(), newSqlSource, mappedStatement.getSqlCommandType());
//        builder.resource(mappedStatement.getResource());
//        builder.fetchSize(mappedStatement.getFetchSize());
//        builder.statementType(mappedStatement.getStatementType());
//        builder.keyGenerator(mappedStatement.getKeyGenerator());
//        if ((mappedStatement.getKeyProperties() != null) && (mappedStatement.getKeyProperties().length != 0)) {
//            StringBuilder keyProperties = new StringBuilder();
//            for (String keyProperty : mappedStatement.getKeyProperties()) {
//                keyProperties.append(keyProperty).append(StrUtil.COMMA);
//            }
//            keyProperties.delete(keyProperties.length() - 1, keyProperties.length());
//            builder.keyProperty(keyProperties.toString());
//        }
//
//        builder.timeout(mappedStatement.getTimeout());
//        builder.parameterMap(mappedStatement.getParameterMap());
//        builder.resultMaps(mappedStatement.getResultMaps());
//        builder.resultSetType(mappedStatement.getResultSetType());
//        builder.cache(mappedStatement.getCache());
//        builder.flushCacheRequired(mappedStatement.isFlushCacheRequired());
//        builder.useCache(mappedStatement.isUseCache());
//        return builder.build();
//    }
//
//    @AllArgsConstructor
//    class BoundSqlSqlSource implements SqlSource {
//        private BoundSql boundSql;
//
//        @Override
//        public BoundSql getBoundSql(Object parameterObject) {
//            return boundSql;
//        }
//    }
//
//}